﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Webitel.Devices
{
	public static class YealinkP4K
	{
		#region Dll declarations
		internal const string YLHOOK = @"Yealink.dll";

		private static bool isDialing = false;
		public static bool IsDialing
		{
			get { return isDialing; }
		}

		private static bool usbconnected = false;
		public static bool Connected
		{
			get { return usbconnected; }
		}
		private static PHONE_STATUS _status;

		public static PHONE_STATUS PhoneStatus
		{
			get { return _status; }
		}

		[DllImport(YLHOOK, EntryPoint = "initInstance", CallingConvention = CallingConvention.StdCall)]
		public static extern bool initDevice();
		public static void InitDevice()
		{
			initDevice();
		}
		[DllImport(YLHOOK, EntryPoint = "openDevice", CallingConvention = CallingConvention.StdCall)]
		private static extern bool OpenDevice();
		[DllImport(YLHOOK, EntryPoint = "deviceClose", CallingConvention = CallingConvention.StdCall)]
		public static extern void deviceClose();

		public static void DeviceClose()
		{
			deviceClose();
		}

		[DllImport(YLHOOK, EntryPoint = "setRing", CallingConvention = CallingConvention.StdCall)]
		public static extern void SetRing();

		[DllImport(YLHOOK, EntryPoint = "enableSpeaker", CallingConvention = CallingConvention.StdCall)]
		public static extern void EnableSpeaker();

		[DllImport(YLHOOK, EntryPoint = "enableLedLight", CallingConvention = CallingConvention.StdCall)]
		public static extern void EnableLedLight();

		[DllImport(YLHOOK, EntryPoint = "disableLedLight", CallingConvention = CallingConvention.StdCall)]
		public static extern void DisableLedLight();

		[DllImport(YLHOOK, EntryPoint = "genReady", CallingConvention = CallingConvention.StdCall)]
		public static extern void genReady();

		public static void GenReady()
		{
			if (isDialing)
				GenDialing();
			else
				genReady();
		}

		[DllImport(YLHOOK, EntryPoint = "genDialing", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenDialing();
		[DllImport(YLHOOK, EntryPoint = "genConnecting", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenConnecting();
		[DllImport(YLHOOK, EntryPoint = "genRingback", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenRingback();
		[DllImport(YLHOOK, EntryPoint = "genCallFail", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenCallFail();
		[DllImport(YLHOOK, EntryPoint = "genInTalk", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenInTalk();
		[DllImport(YLHOOK, EntryPoint = "genOnHold", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenOnHold();
		[DllImport(YLHOOK, EntryPoint = "genOutTalk", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenOutTalk();
		[DllImport(YLHOOK, EntryPoint = "genCallIn", CallingConvention = CallingConvention.StdCall)]
		public static extern void GenCallIn();
		[DllImport(YLHOOK, EntryPoint = "showLCDText", CallingConvention = CallingConvention.StdCall)]
		private static extern void showLCDText([MarshalAs(UnmanagedType.LPStr)] StringBuilder str);
		public static void ShowLCDText(string val)
		{
			showLCDText(new StringBuilder(val));
		}
		[DllImport(YLHOOK, EntryPoint = "setLCDText", CallingConvention = CallingConvention.StdCall)]
		private static extern void setLCDText([MarshalAs(UnmanagedType.LPStr)] StringBuilder str);
		public static void SetLCDText(string val)
		{
			setLCDText(new StringBuilder(val));
		}
	
		#endregion Dll declarations

		#region Callback declarations

		[DllImport(YLHOOK, EntryPoint = "onKeyPressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onKeyPressCallback(OnKeyPressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onKeyUpCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onKeyUpCallback(OnKeyUpHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onOffHookCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onOffHookCallback(OnOffHookHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onHangUpCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onHangUpCallback(OnHangUpHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onDialDigitCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onDialDigitCallback(OnDialDigitHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onCustomEvent", CallingConvention = CallingConvention.StdCall)]
		private static extern void onCustomEvent(OnCustomEventHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onUSBConnectCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onUSBConnectCallback(OnUSBConnectHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onUSBDisonnectCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onUSBDisonnectCallback(OnUSBDisonnectHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onDialPressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onDialPressCallback(OnDialPressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onDeletePressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onDeletePressCallback(OnDeletePressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onInPressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onInPressCallback(OnInPressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onOutPressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onOutPressCallback(OnOutPressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onUpPressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onUpPressCallback(OnUpPressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onDownPressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onDownPressCallback(OnDownPressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onSymbolressCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onSymbolressCallback(OnSymbolPressHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onPhoneStatusChangedCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onPhoneStatusChangedCallback(OnPhoneStatusChangeHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onFlashPressedCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onFlashPressedCallback(OnFlashPressedHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onRedialPressedCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onRedialPressedCallback(OnRedialPressedHandler cb);

		[DllImport(YLHOOK, EntryPoint = "onHelpPressedCallback", CallingConvention = CallingConvention.StdCall)]
		private static extern void onHelpPressedCallback(OnHelpPressedHandler cb);

		#region Events
		public static event OnKeyPressHandler KeyPressed;
		public static event OnKeyUpHandler KeyUpped;
		public static event OnDialDigitHandler DialDigitPressed;
		public static event OnOffHookHandler HookUp;
		public static event OnHangUpHandler HangUp;
		public static event OnUSBConnectHandler USBConnect;
		public static event OnUSBDisonnectHandler USBDisonnect;
		public static event OnDialPressHandler DialPressed;
		public static event OnDeletePressHandler DeletePressed;
		public static event OnInPressHandler InPressed;
		public static event OnOutPressHandler OutPressed;
		public static event OnUpPressHandler UpPressed;
		public static event OnDownPressHandler DownPressed;
		public static event OnSymbolPressHandler SymbolPressed;
		public static event OnPhoneStatusChangeHandler PhoneStatusChanged;
		public static event OnFlashPressedHandler FlashPressed;
		public static event OnRedialPressedHandler RedialPressed;
		public static event OnHelpPressedHandler HelpPressed;
		#endregion Events


		#region Delegates
		public delegate void OnKeyPressHandler(int key);
		public delegate void OnKeyUpHandler(int key);
		public delegate void OnDialDigitHandler(int key);
		public delegate void OnOffHookHandler();
		public delegate void OnHangUpHandler();
		public delegate void OnCustomEventHandler(int ev, int val);
		public delegate void OnUSBConnectHandler();
		public delegate void OnUSBDisonnectHandler();
		public delegate void OnDialPressHandler();
		public delegate void OnDeletePressHandler();
		public delegate void OnInPressHandler();
		public delegate void OnOutPressHandler();
		public delegate void OnUpPressHandler();
		public delegate void OnDownPressHandler();
		public delegate void OnSymbolPressHandler(int key);
		public delegate void OnPhoneStatusChangeHandler(PHONE_STATUS status);
		public delegate void OnFlashPressedHandler();
		public delegate void OnRedialPressedHandler();
		public delegate void OnHelpPressedHandler();
		#endregion Delegates

		static OnKeyPressHandler dKeyPressed = new OnKeyPressHandler(OnKeyPressed);
		static OnKeyUpHandler dKeyUpped = new OnKeyUpHandler(OnKeyUpped);
		static OnDialDigitHandler dDialDigit = new OnDialDigitHandler(OnDialDigit);
		static OnOffHookHandler dOffHook = new OnOffHookHandler(OnOffHook);
		static OnHangUpHandler dHangUp = new OnHangUpHandler(OnHangUp);
		static OnCustomEventHandler dTest = new OnCustomEventHandler(OnCustomEvent);
		static OnUSBConnectHandler dUSBConnect = new OnUSBConnectHandler(OnUSBConnect);
		static OnUSBDisonnectHandler dUSBDisonnect = new OnUSBDisonnectHandler(OnUSBDisonnect);
		static OnDialPressHandler dDialPressed = new OnDialPressHandler(OnDialPress);
		static OnDeletePressHandler dDeletePressed = new OnDeletePressHandler(OnDeletePress);
		static OnInPressHandler dInPressed = new OnInPressHandler(OnInPress);
		static OnOutPressHandler dOutPressed = new OnOutPressHandler(OnOutPress);
		static OnUpPressHandler dUpPressed = new OnUpPressHandler(OnUpPress);
		static OnDownPressHandler dDownPressed = new OnDownPressHandler(OnDownPress);
		static OnSymbolPressHandler dSymbolPressed = new OnSymbolPressHandler(OnSymbolPress);
		static OnPhoneStatusChangeHandler dPhoneStatusChanged = new OnPhoneStatusChangeHandler(OnPhoneStatusChange);
		static OnFlashPressedHandler dFlashPressed = new OnFlashPressedHandler(OnFlashPressed);
		static OnRedialPressedHandler dRedialPressed = new OnRedialPressedHandler(OnRedialPressed);
		static OnHelpPressedHandler dHelpPressed = new OnHelpPressedHandler(OnHelpPressed);

		private static void OnHelpPressed()
		{
			if (null != HelpPressed)
			{
				HelpPressed();
			}
		}

		private static void OnFlashPressed()
		{
			FlashPressed();
		}
		private static void OnRedialPressed()
		{
			RedialPressed();
		}
		private static void OnPhoneStatusChange(PHONE_STATUS status)
		{
			_status = status;
			if (null != PhoneStatusChanged)
			{
				PhoneStatusChanged(status);
			}
		}
		private static void OnSymbolPress(int key)
		{
			if (null != SymbolPressed)
			{
				SymbolPressed(key);
			}
		}
		private static void OnInPress()
		{
			if (null != InPressed)
			{
				InPressed();
			}
		}
		private static void OnOutPress()
		{
			if (null != OutPressed)
			{
				OutPressed();
			}
		}
		private static void OnUpPress()
		{
			if (null != UpPressed)
			{
				UpPressed();
			}
		}
		private static void OnDownPress()
		{
			if (null != DownPressed)
			{
				DownPressed();
			}
		}
		private static void OnDeletePress()
		{
			if (null != DeletePressed)
			{
				DeletePressed();
			}
		}
		private static void OnDialPress()
		{
			if (null != DialPressed)
			{
				DialPressed();
			}
		}
		private static void OnUSBConnect()
		{
			usbconnected = true;
			if (null != USBConnect)
			{
				USBConnect();
			}
		}
		private static void OnUSBDisonnect()
		{
			usbconnected = false;
			if (null != USBDisonnect)
			{
				USBDisonnect();
			}
		}
		private static void OnKeyPressed(int key)
		{
			if (null != KeyPressed)
			{
				KeyPressed(key);
			}
		}
		private static void OnKeyUpped(int key)
		{
			if (null != KeyUpped)
			{
				KeyUpped(key);
			}
		}
		private static void OnOffHook()
		{
			isDialing = true;
			if (null != HookUp)
			{
				HookUp();
			}
		}
		private static void OnHangUp()
		{
			isDialing = false;
			if (null != HangUp)
			{
				HangUp();
			}
		}
		private static void OnDialDigit(int key)
		{
			if (null != DialDigitPressed)
			{
				DialDigitPressed(key);
			}
		}		
		private static void OnCustomEvent(int _event, int _value)
		{
			
		}
		#endregion
		
		public static bool Open()
		{
			try
			{
				InitDevice();
				int i = 0;
				while (!Loaded && i < 3) i++;
				Subscribe();
			}
			catch (Exception e)
			{
				EventLog.WriteEntry("Yealink", e.Message);
				return false;
			}
			return Loaded;
		}

		private static void Subscribe()
		{ 
			if (Loaded)
			{
				//onCustomEvent(OnCustomEvent);
				onKeyPressCallback(dKeyPressed);
				onDialDigitCallback(dDialDigit);
				onKeyUpCallback(dKeyUpped);
				onOffHookCallback(dOffHook);
				onHangUpCallback(dHangUp);
				onUSBConnectCallback(dUSBConnect);
				onUSBDisonnectCallback(dUSBDisonnect);
				onDialPressCallback(dDialPressed);
				onDeletePressCallback(dDeletePressed);
				onInPressCallback(dInPressed);
				onOutPressCallback(dOutPressed);
				onUpPressCallback(dUpPressed);
				onDownPressCallback(dDownPressed);
				onSymbolressCallback(dSymbolPressed);
				onPhoneStatusChangedCallback(dPhoneStatusChanged);
				onFlashPressedCallback(dFlashPressed);
				onRedialPressedCallback(dRedialPressed);
				onHelpPressedCallback(dHelpPressed);
			}
		}

		public static bool Loaded
		{
			get { return OpenDevice();}
		}
	}
	
	public enum PHONE_TONE_TYPE
	{
		PHONE_TONE_TYPE_UNKNOW = 0,
		PHONE_TONE_TYPE_SILENCE = 1,
		PHONE_TONE_TYPE_MUTE = 2,
		PHONE_TONE_TYPE_DIAL = 3,
		PHONE_TONE_TYPE_CONNECTING = 4,
		PHONE_TONE_TYPE_RINGBACK = 5,
		PHONE_TONE_TYPE_BUSY = 6,
		PHONE_TONE_TYPE_UNDEFINED = -1,
	}
	public enum CHANNEL_TYPE
	{
		CHANNEL_PSTN = 0,
		CHANNEL_USB = 1
	}
	public enum PHONE_STATUS
	{
		PHONE_STATUS_READY = 4096,
		PHONE_STATUS_DIALING,
		PHONE_STATUS_CONNECTING,
		PHONE_STATUS_CALLFAIL,
		PHONE_STATUS_RINGBACK,
		PHONE_STATUS_CALLIN,
		PHONE_STATUS_CALLMISS,
		PHONE_STATUS_CALLREFUSED,
		PHONE_STATUS_INTALK,
		PHONE_STATUS_ONHOLD,
		PHONE_STATUS_UNHOLD,
		PHONE_STATUS_OUTTALK,

		PHONE_STATUS_DRAWTEXT,
		PHONE_STATUS_DRAWBMP,
		PHONE_STATUS_INVERTRECT,
		PHONE_STATUS_DRAWTODEVICE,
		PHONE_STATUS_LEDCTRL,
		PHONE_STATUS_RINGCTRL,
		PHONE_STATUS_TONECTRL,
		PHONE_STATUS_PSTNDIALING
	}
}
